#ifndef DOXYGENPARSER_H
#define DOXYGENPARSER_H

#include <set>
#include <wx/popupwin.h>
#include "parser/token.h"

class CodeCompletion;
class TokenTree;
class M_Code_Editor;
class ConfigManager;
class wxHtmlLinkEvent;

namespace Doxygen {
  enum KeywordsIds {
    NO_KEYWORD,
    PARAM,
    RETURN, RESULT,
    BRIEF, SHORT,
    SA, SEE,
    CLASS, STRUCT,
    UNION,
    ENUM,
    NAMESPACE,
    FN,
    VAR,
    DEF,
    CODE,
    ENDCODE,
    NESTED_KEYWORDS_BEGIN,
    B = NESTED_KEYWORDS_BEGIN,
    KEYWORDS_COUNT
  };

  enum KeywordsRanges {
    RANGE_UNKNOWN,
    RANGE_PARAGRAPH,
    RANGE_BLOCK,
    RANGE_LINE,
    RANGE_WORD
  };

  struct DoxygenParser {
      static const wxString Keywords[];
      static const int KwCount;
      static const wxString NewLineReplacment;
      DoxygenParser();
      int FindNextKeyword( const wxString& doc );
      int GetArgument( const wxString& doc, int range, wxString& output );
      int GetPosition() const;
      void ReplaceInDoc( wxString& doc, size_t start, size_t count, const wxString& str );
      void ReplaceCurrentKeyword( wxString& doc, const wxString& str );
    protected:
      int CheckKeyword( const wxString& doc );
      int GetParagraphArgument( const wxString& doc, wxString& output );
      void GetWordArgument( const wxString& doc, wxString& output );
      void GetBlockArgument( const wxString& doc, wxString& output );
      int GetLineArgument( const wxString& doc, wxString& output );
      bool IsKeywordBegin( const wxString& doc ) const;
      bool IsOneOf( wxChar c, const wxChar* chars ) const;
    protected:
      bool IsEnd( const wxString& doc ) const;
      int GetEndLine( const wxString& doc ) const;
      bool SkipDecorations( const wxString& doc );
      bool HandleNewLine( const wxString& doc, wxString& output, const wxString& replaceWith = NewLineReplacment );
      int m_FoundKw;
      int m_Pos;
  };

}

class DocumentationHelper {
  public:
    enum Command {
      cmdNone,
      cmdDisplayToken,
      cmdSearch,
      cmdSearchAll,
      cmdOpenDecl,
      cmdOpenImpl,
      cmdClose
    };
    static wxString DoxygenToHTML( const wxString& doc );
    static wxString ConvertTypeToAnchor( wxString fullType );
    static wxString ConvertArgsToAnchors( wxString args );
    static wxString ExtractTypeAndName( wxString type, wxString* outName = 0 );
    static wxString CommandToAnchor( Command cmd, const wxString& name, const wxString* args = 0 );
    static wxString CommandToAnchorInt( Command cmd, const wxString& name, int arg0 );
    static Command HrefToCommand( const wxString& href, wxString& args );
    static const wxChar separatorTag;
    static const wxString commandTag;
    DocumentationHelper( CodeCompletion* cc );
    ~DocumentationHelper();
    void OnAttach();
    void OnRelease();
    wxString GenerateHTML( int tokenIdx, TokenTree* tree );
    wxString GenerateHTML( const TokenIdxSet& tokensIdx, TokenTree* tree );
    void RereadOptions( ConfigManager* cfg );
    void WriteOptions( ConfigManager* cfg );
    bool IsEnabled() { return m_Enabled; }
    void SetEnabled( bool enabled ) { m_Enabled = enabled; }
  protected:
    void SaveTokenIdx();
  public:
    wxString OnDocumentationLink( wxHtmlLinkEvent& event, bool& dismissPopup );
  protected:
    CodeCompletion* m_CC;
    int m_CurrentTokenIdx, m_LastTokenIdx;
    bool m_Enabled;
};

#endif
